import * as vscode from "vscode";
import voxelType from "@ap/types/voxelType";
import insertCode from "@ap/util/vscode/insertCode";

interface ExtendedQuickPickItem extends vscode.QuickPickItem {}

const dataBySearch: ExtendedQuickPickItem[] = [];

/**
 * 表示 Visual Studio Code 中地图树视图的一个项目。
 * 继承 vscode.TreeItem 并添加特定于应用程序的属性，如 children。
 */
class MapTreeItem extends vscode.TreeItem {
  children?: MapTreeItem[];

  /**
   * 构造 MapTreeItem 的实例。
   */
  constructor(
    public readonly label: string,
    public readonly collapsibleState: vscode.TreeItemCollapsibleState,
    public readonly description?: string,
    public readonly tooltip?: string,
  ) {
    super(label, collapsibleState);
  }
}

/**
 * 为 Visual Studio Code 中的地图树视图提供数据。
 * 实现 vscode.TreeDataProvider 接口以提供 getTreeItem、getChildren 和 refresh 功能。
 */
export default class VoxelMapTreeDataProvider
  implements vscode.TreeDataProvider<MapTreeItem>
{
  // 用于信号树数据已更改的 EventEmitter。
  private _onDidChangeTreeData: vscode.EventEmitter<MapTreeItem | undefined> =
    new vscode.EventEmitter<MapTreeItem | undefined>();

  // 当树数据发生变化时触发的事件。
  readonly onDidChangeTreeData: vscode.Event<MapTreeItem | undefined> =
    this._onDidChangeTreeData.event;

  /**
   * 获取给定元素的树项。
   * @param element 要获取树项的元素。
   * @returns 给定元素的树项。
   */
  getTreeItem(element: MapTreeItem): vscode.TreeItem {
    return element;
  }

  /**
   * 异步获取给定元素的子项。
   * 如果未指定元素，则获取树的根元素。
   * @param element 要获取其子项的元素。
   * @returns 一个 Promise，解析为表示子项的 MapTreeItem 数组。
   */
  async getChildren(element?: MapTreeItem | undefined): Promise<MapTreeItem[]> {
    if (!element) {
      const mapData = this.buildTree();
      return mapData;
    }
    // 返回指定元素的子项（如果存在）。
    return element.children || [];
  }

  /**
   * 从扁平的地图数据列表构造树结构。
   * @param data 表示地图数据的扩展快速选择项列表。
   * @returns 表示构造的树的根节点的 MapTreeItem 数组。
   */
  private buildTree(): MapTreeItem[] {
    const data: MapTreeItem[] = [];
    Object.entries(voxelType).forEach(([key, value]) => {
      const treeItem = new MapTreeItem(
        key,
        vscode.TreeItemCollapsibleState.Collapsed,
      );
      treeItem.children = this.buildTree2(value);
      data.push(treeItem);
    });
    return data;
  }

  private buildTree2(
    value: Record<string, (string | number)[]>,
  ): MapTreeItem[] {
    const data: MapTreeItem[] = [];
    Object.entries(value).forEach(([key, value]) => {
      data.push(
        new MapTreeItem(
          key,
          vscode.TreeItemCollapsibleState.None,
          value[0].toString(),
          value.length > 3
            ? String(value[3])
            : value.length > 2
              ? String(value[2])
              : "",
        ),
      );
      addSearchData(key, value);
    });
    return data;
  }

  async dataBySearchShowBar() {
    if (dataBySearch.length < 1) {
      Object.entries(voxelType).forEach(([key, value]) => {
        dataBySearch.push({
          label: key,
          kind: vscode.QuickPickItemKind.Separator,
        });
        Object.entries(value).forEach(([key, value]) => {
          addSearchData(key, value);
        });
      });
    }
    const selectedOption = await vscode.window.showQuickPick(dataBySearch, {
      title: "方块速查表",
      matchOnDescription: true,
      canPickMany: false,
      placeHolder: "输入要查询的方块名称或ID",
      ignoreFocusOut: true,
    });

    if (selectedOption) {
      const selectedOption2 = await vscode.window.showQuickPick(
        [
          {
            label: "插入方块名称",
            id: 1,
          },
          {
            label: "方块名称转方块ID",
            id: 2,
          },
          {
            label: "方块ID转方块名称",
            id: 3,
          },
        ],
        {
          title: "你已选择【" + selectedOption.label + "】方块",
          matchOnDescription: true,
          canPickMany: false,
        },
      );
      if (selectedOption2) {
        switch (selectedOption2.id) {
          case 1:
            insertCode(selectedOption.label);
            break;
          case 2:
            insertCode(`voxels.id('${selectedOption.label}')`);
            break;
          case 3:
            insertCode(`voxels.name(${selectedOption.description})`);
            break;
        }
      }
    }
  }

  /**
   * 刷新树数据，导致树视图重新获取数据。
   */
  refresh(): void {
    this._onDidChangeTreeData.fire(undefined);
  }
}

function addSearchData(label: string, value: (string | number)[]) {
  const description = String(value[0]);
  const detail =
    value.length > 3
      ? String(value[3])
      : value.length > 2
        ? String(value[2])
        : "";
  dataBySearch.push({
    label,
    description,
    detail,
  });
}
